//
// GPSMapEdit
// (c) Konstantin Galichsky (kg@geopainting.com), 2002-2007
//
// Create new object.
//

# include "StdAfx.h"
# include "CreateObject.h"
# include "UndoRedo.h"
# include "Label.h"
# include "Types.h"
# include "MapView.h"

class CCreateObjectAction : public CEditAction {
  public:
	CCreateObjectAction (points_t & _points, RGN_KIND _Kind, size_t _cLevel, rgn_t ** _ppRgn) :
		m_pRgn (NULL),
		m_ppRgnRet (_ppRgn),
		m_Kind (_Kind),
		m_cLevel (_cLevel)
	{
		m_points.swap (_points);
	}

	virtual void GetName (string_t & _str) const;
	virtual cu_t CanUndo () const {return cuYes;}
	virtual bool Do ();
	virtual void Undo ();
	virtual void Redo ();

  private:
	const RGN_KIND m_Kind;
	const size_t m_cLevel;
	points_t m_points;
	rgn_t * m_pRgn;
	rgn_t ** m_ppRgnRet;
};

void CCreateObjectAction::GetName (string_t & _str) const {
	_str.append ("create ");
	if (m_Kind < rkMax)
		_str.append (g_strKinds [m_Kind]);
}

bool CCreateObjectAction::Do () {
	CCritSec::CLock lock (g_cs);

	assert (m_Kind < rkMax);
	assert (! m_pRgn);

	// Create the new object.
	const rgns_t::iterator iRgn = g_map.CreateRgnIt (m_Kind);
	m_pRgn = & * iRgn;

	assert (m_ppRgnRet);
	* m_ppRgnRet = m_pRgn;

	// Initialize the object.
	m_pRgn->dwFlags |= rgn_t::fModified;
	m_pRgn->strLabel = "";
	m_pRgn->SetType (g_map.pTypeSet->GetUnknownTD (), 0, m_Kind);

	if (m_Kind == rkPolyline || m_Kind == rkPolygon) {
		// Create the element of the rgn.
		m_pRgn->elements.push_back (rgn_element_t ());
		rgn_element_t & element = m_pRgn->elements.back ();

		// Initialize the element of rgn.
		element.cFileOffset = -1;
		element.cLevel      = m_cLevel;
		element.points.swap (m_points);
	} else {
		// Create the origin of the rgn.
		m_pRgn->origins.push_back (rgn_origin_t ());
		rgn_origin_t & origin = m_pRgn->origins.back ();

		// Initialize the origin of rgn.
		origin.cFileOffset = -1;
		origin.cLevel = m_cLevel;
		assert (m_points.size () == 1);
		origin.point = m_points [0];
	}

	m_pRgn->RefreshAttributes (g_map);

	g_Selection.clear ();

	// Add new object to the selection.
	find_info_t fi;
	fi.pLayer           = & g_map.layers [m_Kind];
	fi.iRgn             = iRgn;
	fi.cElementOrOrigin = -1;
	g_Selection.push_back (fi);

	return true;
}

void CCreateObjectAction::Undo () {
	CCritSec::CLock lock (g_cs);

	assert (m_pRgn);
	m_pRgn->Delete (g_map);

	m_pRgn->RefreshAttributes (g_map);
}

void CCreateObjectAction::Redo () {
	assert (m_pRgn);
	m_pRgn->Undelete (g_map);

	m_pRgn->RefreshAttributes (g_map);
}

////////////////////////////////////////////////

rgn_t & CreateObject (points_t & _points, RGN_KIND _Kind, size_t _cLevel) {
	assert (_Kind < rkMax);
	rgn_t * pRgn = NULL;
	PerformEditAction (new CCreateObjectAction (_points, _Kind, _cLevel, & pRgn));
	return * pRgn;
}
